package it.allerj.common.utility;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileUtil {
	public static File setTextToFile(File file,String text){
	    try {
	       
	        RandomAccessFile raf = new RandomAccessFile(file, "rw");
	    
	        // Read a character
	        //char ch = raf.readChar();
	    
	        // Seek to end of file
	        raf.seek(file.length());
	    
	        // Append to the end
	        raf.writeChars(text);
	        raf.close();
	    } catch (IOException e) {
	    	e.printStackTrace();
	    }


		try {
	        BufferedWriter out = new BufferedWriter(new FileWriter(file));
	        out.write(text);
	        out.close();
	    } catch (IOException e) {
	    	e.printStackTrace();
	    }
	    return file;
	}
	public static String getTextFromFile(File file){
		 StringBuffer sb = new StringBuffer("") ;
		try {
	        BufferedReader in = new BufferedReader(new FileReader(file));
	        String str;
	       
	        while ((str = in.readLine()) != null) {
	        	sb.append(str);
	        }
	        in.close();
	    } catch (IOException e) {
	    	System.out.println("["+FileUtil.class.getName()+"] getTextFromFile() : "+e.getMessage());
	    }
	    return sb.toString();
	}
	public static File getFileFromByteArray(File file, byte[] bytes, boolean append){
		// Write bbuf to filename
	    ByteBuffer bbuf = getByteBufferFromByteArray(bytes);
	    //File file = new File("filename");
	    
	    // Set to true if the bytes should be appended to the file;
	    // set to false if the bytes should replace current bytes
	    // (if the file exists)
	    //boolean append = false;
	    
	    try {
	        // Create a writable file channel
	        FileChannel wChannel = new FileOutputStream(file, append).getChannel();
	    
	        // Write the ByteBuffer contents; the bytes between the ByteBuffer's
	        // position and the limit is written to the file
	        wChannel.write(bbuf);
	    
	        // Close the file
	        wChannel.close();
	    } catch (IOException e) {
	    }
	    return file;
	}
	 public static byte[] getByteArrayFromFile(File file) throws IOException {
	        InputStream is = new FileInputStream(file);
	    
	        // Get the size of the file
	        long length = file.length();
	    
	        // You cannot create an array using a long type.
	        // It needs to be an int type.
	        // Before converting to an int type, check
	        // to ensure that file is not larger than Integer.MAX_VALUE.
	        if (length > Integer.MAX_VALUE) {
	            // File is too large
	        }
	    
	        // Create the byte array to hold the data
	        byte[] bytes = new byte[(int)length];
	    
	        // Read in the bytes
	        int offset = 0;
	        int numRead = 0;
	        while (offset < bytes.length
	               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
	            offset += numRead;
	        }
	    
	        // Ensure all the bytes have been read in
	        if (offset < bytes.length) {
	            throw new IOException("Could not completely read file "+file.getName());
	        }
	    
	        // Close the input stream and return bytes
	        is.close();
	        return bytes;
	    }
	 public static ByteBuffer getByteBufferFromByteArray(byte[] bytes){
		    ByteBuffer bbuf = ByteBuffer.wrap(bytes);
		    return bbuf;
	 }
	 public static byte[] getByteArrayFromByteBuffer(int start, int end, ByteBuffer bbuf){
		 bbuf.clear();
		 byte[] bytes = new byte[bbuf.capacity()];
		 bbuf.get(bytes, start, end);
		 return bytes;
	 }
	 // Process all files and directories under dir
    public static void visitAllDirsAndFiles(File dir, ProcessingRoutine processingRoutine) {
    	processingRoutine.process(dir);
    
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllDirsAndFiles(new File(dir, children[i]),processingRoutine);
            }
        }
    }
    
    // Process only directories under dir
    public static void visitAllDirs(File dir, ProcessingRoutine processingRoutine) {
        if (dir.isDirectory()) {
        	processingRoutine.process(dir);
    
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllDirs(new File(dir, children[i]),processingRoutine);
            }
        }
    }
    
    // Process only files under dir
    public static void visitAllFiles(File dir, ProcessingRoutine processingRoutine) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                visitAllFiles(new File(dir, children[i]), processingRoutine);
            }
        } else {
        	processingRoutine.process(dir);
        }
    }
    
    public static File getDirByName(String urlDir){
    	return new File(urlDir);

    }
    
    public interface ProcessingRoutine{
    	public void process(File dir);
    	public void processString(String line);
    	public Object getReults();
    }
//  Deletes all files and subdirectories under dir.
    // Returns true if all deletions were successful.
    // If a deletion fails, the method stops attempting to delete and returns false.
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
    
        // The directory is now empty so delete it
        return dir.delete();
    }
    public static void readTextFileAndProcess(File file, ProcessingRoutine processingRoutine){
    	try {
            BufferedReader in = new BufferedReader(new FileReader(file));
            String str;
            while ((str = in.readLine()) != null) {
            	processingRoutine.processString(str);
            }
            in.close();
        } catch (IOException e) {
			e.printStackTrace();
        }
    }
    
    
    /**
     * Data una url relativa al package (es.: it/micra/properties/fileditesto.txt) mi restituisce un line number reader per leggere un file riga per riga
     * @param url
     * @return
     */
    public static LineNumberReader getLineNumberReader(String url)
    {
    	return new LineNumberReader( new InputStreamReader(FileUtil.class.getClassLoader().getResourceAsStream(url)));
    }
    
    /**
     * dato un file mi restituisce un line number reader per leggere un file riga per riga
     * 
     * @param file
     * @return
     * @throws FileNotFoundException
     */
    public static LineNumberReader getLineNumberReader(File file) throws FileNotFoundException
    {
    	return new LineNumberReader( new FileReader(file));
    }

}
